package control
{
	import flash.events.Event;
	import flash.system.System;
	
	import model.Model;
	import model.Page;
	
	import mx.collections.ArrayCollection;
	
	import service.LocalStorageService;
	import service.StorageService;
	
	import textdiff.Report;
	import textdiff.TextDiff;
	
	import wiki.event.WikiEvent;
	import wiki.parser.WikiParser;
	import wiki.parser.WikiPattern;
	
	/**
	 * The front controller for this application. 
	 * It provides the single interface to all functionality of the application.
	 * 
	 * This class is supposed to be a singleton class, so do not instantiate it. 
	 * In stead, use FrontController.instance to gain access to the singleton.
	 */
	public class FrontController {
		
		/**
		 * The constructor for this class.
		 * Should be private, but AS3 does not allow that.
		 */
		public function FrontController() {
			// TO DO (in the future): determine whether remote storage service is reachable or not, and
			// decide which storage service to instantiate here.
			
			// for now, all we currently know is the local storage service
			_storageService = new LocalStorageService();
			_storageService.open();
			_storageService.addEventListener(WikiEvent.PAGE_LOADED, pageLoaded);
			//_storageService.addEventListener(WikiEvent.PAGEINDEX_LOADED, pageIndexLoaded);
			
			_wikiParser = new WikiParser();
			_textDiff = new TextDiff();
			
		}
		
	/* --- public functions --- */

		public function get storageService(): StorageService {
			return _storageService;
		}
		
		public function createPage(pageId: String): void  {
			Model.instance.newPage = _storageService.createPage(pageId);
		}
		
		public function loadPage(pageId: String): void {
			// create an empty page first and set it as the current page
			createPage(pageId);
			
			// attempt to load the page from the database
			_storageService.loadPage(pageId);
		}
		
		public function savePageUpdate(pageId: String, text: String): void {
//			var diffReport:Report = _textDiff.compare(
//				Model.instance.currentPage.text.split("\r"),
//				text.split("\r"));
//			_storageService.savePageUpdate(pageId, diffReport.toPatchString());
			_storageService.savePageUpdate(pageId, text);
		}
		
		public function disposePage(pageId: String): void {
			_storageService.disposePage(pageId);
		}
		
		public function loadPageIndex(): void {
			_storageService.loadPageIndex();
		}
		
		public function loadPreviousPage(): void {
			navigate(Model.instance.navigationPath.length-1);
		}
		
		public function loadHomePage(): void {
			loadPage(Page.HOME_PAGE);
			Model.instance.previousPage = null;
			Model.instance.navigationPath.removeAll();
		}
		
		public function navigate(index: int) : void {
			var navpath:ArrayCollection = Model.instance.navigationPath;
			if (index>=0 && navpath.length) {
				var p: Page = navpath.getItemAt(index) as Page;
				loadPage(p.pageId);
				while (navpath.length>index) navpath.removeItemAt(index);
			}
		}
		
		public function generateHTML(text: String): void {
			Model.instance.html = _wikiParser.parse(text);
		}
		
		public function exit(): void {
			//_storageService.close();
			flash.system.System.exit(0);
		}
		
		public static function get instance(): FrontController {
			if (_instance == null) {
				_instance = new FrontController();
			}
			return _instance;
		}
		
	/* --- private functions --- */

		private function pageLoaded(event: Event): void {
			if (event is WikiEvent && event.type == WikiEvent.PAGE_LOADED) {
				var we:WikiEvent = event as WikiEvent;
				if (we.page == null || we.page.isNew()) {
					Model.instance.currentPage = Model.instance.newPage;
				}
				else {
					Model.instance.currentPage = we.page;
				}
				generateHTML(Model.instance.currentPage.text);
			}
		}		

		private function pageIndexLoaded(event: Event): void {
			if (event is WikiEvent && event.type == WikiEvent.PAGEINDEX_LOADED) {
				var we:WikiEvent = event as WikiEvent;
				if (we.pageIndex != null) {
					Model.instance.pageIndex = we.pageIndex;
				}
			}
		}		

		
	/* --- private properties --- */

		private static var _instance: FrontController = null;
		private var _storageService: StorageService;
		private var _wikiParser:WikiParser;
		private var _textDiff:TextDiff;
	}
}